# @FileName  : histogram.py
# @Time      : 2021/11/26 0026  6:06
# @Author    : LuZhaoHui
# @Software  : PyCharm

from collections import Counter
# import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont

DEFAULT_DPI = (300.0, 300.0)


def getImg1File(file):
    try:
        image = Image.open(file)
    except Exception:
        return (0, 0)
    return image.size


def getImg2File(file):
    try:
        image = Image.open(file)
    except Exception:
        return [0, 0, 300, 300]
    dpi = DEFAULT_DPI
    if 'dpi' in image.info.keys():
        dpi = image.info['dpi']
    return [image.size[0], image.size[1], int(dpi[0]), int(dpi[1])]


def getImg3File(file):
    try:
        image = Image.open(file)
    except Exception:
        return (0, 0, 300.0, 300.0, 'RGB')
    if 'dpi' in image.info:
        return image.size + image.info['dpi'] + tuple([image.mode])
    else:
        return image.size + (0.0, 0.0) + tuple([image.mode])


def count_elements1(seq):
    hist = {}
    for i in seq:
        hist[i] = hist.get(i, 0) + 1
    return hist


def count_elements2(seq):
    return Counter(seq)


def getColorScaleIndex(nums):
    a = [0] * 256
    c = []
    k = 0
    for i in range(nums):
        n = int(256 * (i + 1) / nums)
        c.append([k, n - 1])
        for j in range(n - k):
            a[j + k] = i
        k = n
    return a, c


def getLightIndex(nums):
    a = [0] * 256
    c = []
    b = 0
    k = 0
    # d = int(nums * 1000 / 2) / 1000
    while b < 256:
        if (b + nums) > 256:
            nums = 256 - b
        for i in range(nums):
            a[b + i] = k
        c.append([b, b + nums])
        b += nums
        k += 1
    return k, a, c


def getLumExpo(lum, lumIndex, expoField):
    if lum > 0.0:
        lum_index = lumIndex[int(lum * 10)]
        return int(expoField[lum_index])
    return 0


def getLumIndex(nums, field):
    ma = (int(field[nums - 1])) * 10
    a = [0] * ma
    c = []
    begin = 0
    end = 0
    for i, s in enumerate(field):
        end = int(s)
        c.append([float(begin), float(end) - 0.1])
        for k in range(begin * 10, end * 10):
            a[k] = i
        begin = end
    return a, c


def getImageHistogram(name, isRGB, mode=0):
    # img = cv2.imread(name)
    img = cv2.imdecode(np.fromfile(name, dtype=np.uint8), -1)
    if isRGB:
        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    if mode > 2:
        x1 = int(img.shape[1] / mode)
        y1 = int(img.shape[0] / mode)
        x2 = img.shape[1] - x1 * 2
        y2 = img.shape[0] - y1 * 2
        cut = img[y1:y1 + y2, x1:x1 + x2]
        mean = cv2.mean(cut)
        hist = cv2.calcHist([cut], [0], None, [256], [0, 256])
    else:
        mean = cv2.mean(img)
        hist = cv2.calcHist([img], [0], None, [256], [0, 256])
    a = [0] * 256
    av = [0.0] * 256
    for i in range(256):
        a[i] = int(hist[i][0])
        av[i] = round((i * a[i]) / img.size, 3)
    return a, round(mean[0], 3), av


def getImageMean(name, isRGB):
    # return 0.0
    img = cv2.imdecode(np.fromfile(name, dtype=np.uint8), -1)
    if isRGB:
        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    mean = cv2.mean(img)
    return round(mean[0], 3)


# 亮度集合
def getImageMean2(name, isRGB):
    # 4方格
    # img = cv2.imread(name)
    img = cv2.imdecode(np.fromfile(name, dtype=np.uint8), -1)
    if isRGB:
        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    wx = int(img.shape[1] / 2)
    wy = int(img.shape[0] / 2)
    mean = [0.0] * 5
    xy = [(int(wx / 2), int(wy / 2)),
          (0, 0),
          (wx, 0),
          (0, wy),
          (wx, wy)
          ]
    # 中,左上,右上,左下,右下,
    # 最亮，最暗
    ma = 0
    mi = 999.0
    for i, s in enumerate(xy):
        cut = img[s[1]:s[1] + wy, s[0]:s[0] + wx]
        m = cv2.mean(cut)
        mean[i] = round(m[0], 3)
        if i > 0:
            ma = max(mean[i], ma)
            mi = min(mean[i], mi)
    return mean + [ma, mi]


def getImageHistogramSelf(hist256, av256, index, nums):
    a = [0] * nums
    av = [0] * nums
    for i in range(256):
        a[index[i]] += hist256[i]
        av[index[i]] += av256[i]
    return a, av


def getDiff(n1, n2):
    if n1 == 0.0 or n2 == 0.0:
        return 0.0
    return round(abs(n1 - n2) * 100.0 / n1, 3)


def getMis(n1, n2):
    if n1 == 0.0 or n2 == 0.0:
        return 0
    return abs(n1 - n2)


def procRotateImage(name):
    image = Image.open(name)
    image = image.transpose(Image.ROTATE_90)
    image.save(name, dpi=DEFAULT_DPI)


def procLightImage(name, orgLight, desLight, lightRatio, lightMulti):
    img = cv2.imdecode(np.fromfile(name, dtype=np.uint8), -1)
    diff = desLight * lightRatio - orgLight
    if len(img.shape) == 3:
        rows, cols, ch = img.shape
        blank = np.zeros([rows, cols, ch], img.dtype)
    else:
        rows, cols = img.shape
        blank = np.zeros([rows, cols], img.dtype)

    a = 1.0 + diff / orgLight
    b = 1 - a
    g = lightMulti
    ret = cv2.addWeighted(img, a, blank, b, g)
    # cv2.imwrite(name, ret)
    cv2.imencode('.jpg', ret)[1].tofile(name)
    # save dpi
    new_img = Image.open(name)
    new_img.save(name, dpi=DEFAULT_DPI)


def readLight(name, isRGB, isLum, isColor, scale, index, weight):
    size = getImg3File(name)
    if isLum:
        a256, mean, av256 = getImageHistogram(name, isRGB)
        hist5, av5 = getImageHistogramSelf(a256, av256, index, scale)
    else:
        mean = getImageMean(name, isRGB)
        hist5 = [0.0] * scale
        av5 = [0.0] * scale

    mean2 = getImageMean2(name, isRGB)
    shist = []
    calcAv = 0.0
    if isColor:
        for i in range(scale):
            shist.append([round(hist5[i] * 100 / (size[0] * size[1]), 3), av5[i]])
            calcAv += weight[i] * av5[i]

    return [mean,  # 9 全图亮度
            mean2[0:5] + [getDiff(mean2[5], mean2[0]), getDiff(mean2[5], mean2[6])],  # 10 亮度表
            round(calcAv, 3)]  # 12 估算照度
